package com.heatup.apt.api.service.impl;

import com.heatup.apt.api.service.AccessService;
import com.heatup.apt.api.service.UserService;
import com.heatup.apt.common.constants.DeviceConstants;
import com.heatup.apt.common.constants.OrderContants;
import com.heatup.apt.common.dao.*;
import com.heatup.apt.common.dao.coach.CoachInfoMapper;
import com.heatup.apt.common.exception.OrderException;
import com.heatup.apt.common.exception.OrderNotFoundException;
import com.heatup.apt.common.util.DateUtil;
import com.heatup.apt.common.util.DateUtils;
import com.heatup.apt.common.util.QRCodeUtil;
import com.heatup.apt.model.AccessDevice;
import com.heatup.apt.model.DoorAccessPwd;
import com.heatup.apt.model.QRDoor;
import com.heatup.apt.model.TSysAccessDeviceLog;
import com.heatup.apt.model.coach.CoachInfo;
import com.heatup.apt.model.course.CourseSign;
import com.heatup.apt.model.course.OrderCourse;
import com.heatup.apt.model.management.SysUser;
import com.heatup.apt.model.order.OrderDetail;
import com.heatup.apt.model.order.OrderInfo;
import com.heatup.apt.model.user.UserInfo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by Blank on 2016-10-18.
 */
@Service
public class AccessServiceImpl implements AccessService {

    public static final Logger log = LoggerFactory.getLogger(AccessServiceImpl.class);

    @Resource
    private AccessDeviceMapper accessDeviceMapper;
    @Resource
    private TSysAccessDeviceLogMapper accessDeviceLogMapper;
    @Resource
    private OrderInfoMapper orderInfoMapper;
    @Resource
    private OrderDetailMapper orderDetailMapper;
    @Resource
    private DoorAccessPwdMapper doorAccessPwdMapper;
    @Resource
    private UserService userService;
    @Resource
    private CoachInfoMapper coachInfoMapper;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private CourseSignMapper courseSignMapper;
    /**
     * 更新门禁在线状态
     *
     * @param accessDevice
     * @return
     */
    @Override
    public boolean updateDoorDeviceHeartBeat(AccessDevice accessDevice) {

        if (StringUtils.isNotEmpty(accessDevice.getDeviceSerialId())) {

            //首先查询设备是否存在
            AccessDevice accessDeviceDB = accessDeviceMapper.queryAccessDeviceBySerialId(accessDevice.getDeviceSerialId());
            if (accessDeviceDB != null) {
                accessDevice.setId(accessDeviceDB.getId());
                accessDevice.setDeviceStatus(DeviceConstants.DeviceStatus.online.getIndex());
                accessDevice.setLastUpdateTime(new Date());
                return accessDeviceMapper.updateSelectiveById(accessDevice) > 0;
            }
        }

        return false;

    }


    /**
     * 查询用户密码是否正确
     *
     * @param password 密码
     * @param qrDoor   门禁设备
     * @return true 正确 /false 错误
     */
    @Override
    public boolean checkQRCodePwd(String password, QRDoor qrDoor) {

        Assert.notNull(qrDoor,"QRCode Door params can not be null!" );
        Assert.notNull(qrDoor.getDeviceID(),"QRCode Door param DeviceID can not be null!" );


        //QRCode 密码只有2分钟有效..如果 DB 中存在则说明未过期.QRCode 有效 否则无效
        DoorAccessPwd doorAccessPwd = new DoorAccessPwd();
        doorAccessPwd.setPassword(password);
        doorAccessPwd = doorAccessPwdMapper.selectOne(doorAccessPwd);//TODO 3个 SQL 重构成一个 sql 查询返回处理以提升 SQL 性能
        boolean result = doorAccessPwd != null && new Date().before(doorAccessPwd.getEndTime());

        if (doorAccessPwd != null && doorAccessPwd.getRelationType() != null) {

            //教练或系统用户只校验门店
            if (doorAccessPwd.getRelationType() > 0 && result) {
                AccessDevice accessDevice = accessDeviceMapper.queryAccessDeviceBySerialId(qrDoor.getDeviceID());
                return accessDevice != null && accessDevice.getStoreId() != null && accessDevice.getStoreId().equals(doorAccessPwd.getStoreId());
            }

            //用户需要再次校验订单和门店的有效性
            if (doorAccessPwd.getRelationType().equals(0)) {
                //relationId 即是订单 ID
                if (result && doorAccessPwd.getRelationId() != null) {
                    //检验订单是否 OK

                    OrderDetail orderDetail = orderDetailMapper.queryOrderDetailByOrderId(doorAccessPwd.getRelationId());
                    if (orderDetail != null && orderDetail.getStoreId() != null) {

                        AccessDevice accessDevice = accessDeviceMapper.queryAccessDeviceBySerialId(qrDoor.getDeviceID());
                        return accessDevice != null && accessDevice.getStoreId() != null && accessDevice.getStoreId().equals(orderDetail.getStoreId());
                    }
                }
            }
        }

        return false;
    }


    /**
     * 记录门禁密码使用次数
     *
     * @param serialId
     * @param password
     * @param pwdWasRight
     * @param isSuperPin
     * @return
     */
    @Override
    public boolean updateAccessDevicePWDUsedCount(String serialId, String password, boolean pwdWasRight, boolean isSuperPin) {
        if (StringUtils.isBlank(serialId) || StringUtils.isBlank(password))
            return false;

        TSysAccessDeviceLog accessDeviceLog = accessDeviceLogMapper.queryAccessDeviceLogBySerialIdPwd(serialId, password);
        OrderInfo orderInfo = orderInfoMapper.queryOrderInfoByNowDayPwd(password);

        if (accessDeviceLog == null) {
            log.info("当前门禁日志无此密码使用记录");

            accessDeviceLog = new TSysAccessDeviceLog();
            accessDeviceLog.setDeviceSerialId(serialId);
            if (orderInfo != null && orderInfo.getId() != null && orderInfo.getUserId() != null) {
                accessDeviceLog.setOrderId(orderInfo.getId());
                accessDeviceLog.setUserId(orderInfo.getUserId());
            }
            accessDeviceLog.setUsedPwd(password);
            accessDeviceLog.setUsedPwdCount(1);
            if (pwdWasRight) {
                accessDeviceLog.setUsedPwdSuccessCount(1);
                accessDeviceLog.setUsedPwdFailCount(0);
            } else {
                accessDeviceLog.setUsedPwdSuccessCount(0);
                accessDeviceLog.setUsedPwdFailCount(1);
            }
            if (isSuperPin) {
                accessDeviceLog.setUsedSuperPwdCount(1);
            } else {
                accessDeviceLog.setUsedSuperPwdCount(0);
            }
            accessDeviceLog.setLastestUsedTime(new Date());
            return accessDeviceLogMapper.insertSelective(accessDeviceLog) > 0;
        } else {
            if (orderInfo != null && orderInfo.getId() != null && orderInfo.getUserId() != null) {
                accessDeviceLog.setOrderId(orderInfo.getId());
                accessDeviceLog.setUserId(orderInfo.getUserId());
            }
            accessDeviceLog.setUsedPwdCount((accessDeviceLog.getUsedPwdCount() + 1));
            log.info("当前密码使用次数 ======>>" + accessDeviceLog.getUsedPwdCount());
            if (pwdWasRight) {
                accessDeviceLog.setUsedPwdSuccessCount((accessDeviceLog.getUsedPwdSuccessCount() + 1));
                log.info("当前密码正确使用次数 ======>>" + accessDeviceLog.getUsedPwdSuccessCount());
            } else {
                accessDeviceLog.setUsedPwdFailCount((accessDeviceLog.getUsedPwdFailCount() + 1));
                log.info("当前密码错误使用次数 ======>>" + accessDeviceLog.getUsedPwdFailCount());
            }
            if (isSuperPin) {
                accessDeviceLog.setUsedSuperPwdCount((accessDeviceLog.getUsedSuperPwdCount() + 1));
                log.info("当前超级管理密码使用次数 ======>>" + accessDeviceLog.getUsedSuperPwdCount());
            }
            accessDeviceLog.setLastestUsedTime(new Date());
            return accessDeviceLogMapper.updateSelectiveById(accessDeviceLog) > 0;
        }

    }


    /**
     * 教练验证 教练(用户)点击 我是教练时请求此接口
     *
     * @param userId 用户 ID
     * @return
     */
    @Override
    public Map<String, Object> queryCoachPwdStatus(Integer userId) {
        Map<String, Object> resultMap = new HashMap<>();
        if (userId != null) {
            UserInfo user = userService.getUserInfoById(userId);
            CoachInfo coach = null;
            SysUser sysUser = null;
            if (user != null && user.getMobile() != null) {
                //查询用户是否为教练
                coach = coachInfoMapper.queryCoachByMobile(user.getMobile());
            }
            if (coach != null) {
                //如果是教练 并且用户表中手机号码为空 将教练表中的手机号码更新到用户表中
                if (StringUtils.isBlank(user.getMobile())) {
                    userService.updateMobile(user.getId(), coach.getMobile());
                }
                //查询当前密码是否有效
                List<DoorAccessPwd> accessPwdList = queryDoorPwdByMobile(coach.getMobile());
                log.info("教练 密码数量  ===>" + accessPwdList.size());
                List<DoorAccessPwd> resultList = new ArrayList<>();
                if (accessPwdList.size() > 0) {
                    for (DoorAccessPwd accessPwd : accessPwdList) {
                        if (accessPwd != null && accessPwd.getEndTime().before(new Date())) {
                            resultList.add(accessPwd);
                        }
                    }
                    //密码有效 或密码未过期 跳转到密码显示界面
                    resultMap.put("type", 1);
                    log.info("type = 1 密码有效 或密码未过期 跳转到密码显示界面");
                    resultMap.put("pwd", resultList);
                } else {
                    //未请求密码 或密码已过期 跳转到请求密码界面
                    resultMap.put("type", 2);
                    log.info("type = 2 未请求密码 或密码已过期 跳转到请求密码界面");
                }
            } else {
                //再次查询用户是否为系统用户
                if (user != null) {
                    sysUser = sysUserMapper.querySysUserByMobile(user.getMobile());
                }
                if (sysUser != null) {
                    log.info("系统用户存在");
                    //如果是系统用户 并且用户表中手机号码为空 将教练表中的手机号码更新到用户表中
                    if (StringUtils.isBlank(user.getMobile())) {
                        userService.updateMobile(user.getId(), sysUser.getMobile());
                    }
                    //查询当前密码是否有效
                    List<DoorAccessPwd> accessPwdList = querySystemUserPwdBySysUserId(sysUser.getId());
                    log.info("系统用户 密码数量  ===>" + accessPwdList.size());
                    List<DoorAccessPwd> resultList = new ArrayList<>();
                    if (accessPwdList.size() > 0) {
                        for (DoorAccessPwd accessPwd : accessPwdList) {
                            if (accessPwd != null && accessPwd.getEndTime().before(new Date())) {
                                resultList.add(accessPwd);
                            }
                        }
                        //密码有效 或密码未过期 跳转到密码显示界面
                        resultMap.put("type", 1);
                        log.info("type = 1 系统用户 密码有效 或密码未过期 跳转到密码显示界面");
                        resultMap.put("pwd", resultList);
                    } else {
                        //未请求密码 或密码已过期 跳转到请求密码界面
                        resultMap.put("type", 2);
                        log.info("type = 2 系统用户 未请求密码 或密码已过期 跳转到请求密码界面");
                    }
                } else {
                    //查询不到教练 跳转到绑定教练
                    resultMap.put("type", 3);
                    log.info("type = 3 查询不到教练/系统用户 跳转到绑定教练/系统用户");
                }
            }
        }
        return resultMap;
    }

    /**
     * 生成教练密码 旧系统
     *
     * @param mobile       教练手机号码
     * @param storeId      门店ID (or NULL)
     * @param relationType 密码类型 1 教练密码 2 系统用户密码
     * @return
     */
    @Deprecated
    @Override
    public void createCoachOrSysUserPwd(String mobile, Integer storeId, Integer relationType) {

        // step1 查询当前教练
        CoachInfo coachInfo = coachInfoMapper.queryCoachByMobile(mobile);
        // step2 创建新密码并返回所有有效密码
        if (storeId != null && storeId > 0 && coachInfo != null) {
            createdDoorAccessPwdByRelation(coachInfo.getId(), storeId, 1);
        }
        if (coachInfo == null) {
            //step3 查询系统用户
            SysUser sysUser = sysUserMapper.querySysUserByMobile(mobile);
            if (sysUser != null) {
                //step4 创建新密码并返回所有有效密码
                createdDoorAccessPwdByRelation(sysUser.getId(), storeId, 2);
            }
        }
    }

    /**
     * 根据教练id和门店id创建进店密码
     *
     * @param relationId   订单ID/教练ID/系统用户ID
     * @param storeId      门店ID
     * @param relationType 密码类型 0订单 1教练 2系统用户
     * @return
     */
    @Deprecated
    public DoorAccessPwd createdDoorAccessPwdByRelation(Integer relationId, Integer storeId, Integer relationType) {
        log.info("============================== get coach/sysUser store password start =======================parameter : relationId " + relationId + " storeId " + storeId + "relationType" + relationType);
        DoorAccessPwd accessPwd = new DoorAccessPwd();
        String password = this.getUserPwd(storeId);
        Date end_time = DateUtils.addMinutes(new Date(), 60 * 5);
        accessPwd.setRelationId(relationId);
        accessPwd.setRelationType(relationType);
        accessPwd.setStoreId(storeId);
        accessPwd.setPassword(password);
        accessPwd.setPwdStatus("0");
        accessPwd.setStartTime(new Date());
        accessPwd.setEndTime(end_time);
        accessPwd.setCreatedTime(new Date());
        if (relationType == 1) {
            accessPwd.setRemark("教练获取门店密码");
        } else if (relationType == 2) {
            accessPwd.setRemark("系统用户获取门店密码");
        }
        int bool_insert = doorAccessPwdMapper.createdDoorAccessPwd(accessPwd);
        log.info("============================== get coach/sysUser store password end =======================bool_insert : " + bool_insert);
        return accessPwd;
    }

    public String getUserPwd(int storeId) {
        String doorAccessPwd = "";
        while (true) {
            doorAccessPwd = String.valueOf(Math.round(Math.random() * 1000000));
            int bool = doorAccessPwdMapper.queryDoorAccessPwdByPwd(doorAccessPwd, storeId);
            if (bool == 0 && doorAccessPwd.length() == 6)
                break;
        }
        return doorAccessPwd;
    }

    /**
     * 查询教练门禁密码
     *
     * @param coachId 教练ID
     * @return
     */
    @Override
    public DoorAccessPwd queryCoachAccessPwd(Integer coachId) {
        return doorAccessPwdMapper.queryDoorAccessPwdByRelationId(coachId, 1);
    }

    /**
     * 查询门禁密码密码
     *
     * @param mobile 教练/系统用户手机号码
     * @return
     */
    @Override
    public List<DoorAccessPwd> queryDoorPwdByMobile(String mobile) {
        CoachInfo coachUser = coachInfoMapper.queryCoachByMobile(mobile);
        if (coachUser != null) {
            log.info("查询教练密码");
            return doorAccessPwdMapper.queryDoorAccessPwdListByRelation(coachUser.getId(), 1);
        } else {
            SysUser sysUser = sysUserMapper.querySysUserByMobile(mobile);
            log.info("查询管理系统用户密码");
            if (sysUser != null) {
                return doorAccessPwdMapper.queryDoorAccessPwdListByRelation(sysUser.getId(), 2);
            }
        }
        return null;
    }

    /**
     * 查询管理系统用户密码
     *
     * @param mobile 系统用户手机号码
     * @return
     */
    @Override
    public List<DoorAccessPwd> querySystemUserPwdBySysUserMobile(String mobile) {

        SysUser sysUser = sysUserMapper.querySysUserByMobile(mobile);
        log.info("查询管理系统用户密码");
        if (sysUser != null) {
            return doorAccessPwdMapper.queryDoorAccessPwdListByRelation(sysUser.getId(), 2);
        }
        return null;
    }

    /**
     * 同步门禁离线扫码使用记录
     *
     * @param qrDoor 离线使用数据
     * @return true 同步成功 / false 同步失败
     */
    @Override
    public boolean updateDoorDeviceOfflineData(QRDoor qrDoor) {

        if (qrDoor != null && StringUtils.isNotEmpty(qrDoor.getDeviceID()) && StringUtils.isNotEmpty(qrDoor.getSCode())) {

            Boolean deviceLogList = syncQRCodeUse(qrDoor);
            if (deviceLogList != null) return deviceLogList;

        }

        return false;
    }


    /**
     * 更新二维码使用记录
     *
     * @param qrDoor 密码
     * @return true 成功 / false 失败
     */
    private Boolean syncQRCodeUse(QRDoor qrDoor) {
        TSysAccessDeviceLog deviceLog;
        List<String> ids = Arrays.asList(qrDoor.getSCode().split(","));
        SimpleDateFormat df = new SimpleDateFormat("yyMMddHHmmss");//设置日期格式

        List<TSysAccessDeviceLog> deviceLogList = new ArrayList<>();
        OrderInfo orderInfo;

        for (String id : ids) {
            deviceLog = new TSysAccessDeviceLog();
            deviceLog.setDeviceSerialId(qrDoor.getDeviceID());
            orderInfo = orderInfoMapper.queryOrderInfoByNowDayPwd(id.substring(0, 8));
            if (orderInfo != null) {
                deviceLog.setOrderId(orderInfo.getId());
                deviceLog.setUserId(orderInfo.getUserId());
            }
            deviceLog.setUsedPwd(id.substring(0, 8));
            deviceLog.setUsedPwdCount(1);
            try {
                deviceLog.setLastestUsedTime(df.parse(id.substring(8, 20)));
            } catch (ParseException e) {
                e.printStackTrace();
                log.error("密码使用记录 转换日期时出错 " + e.getMessage() + e.getCause(), e);
            }


            deviceLogList.add(deviceLog);
        }

        if (deviceLogList.size() > 0) {
            return accessDeviceLogMapper.insertBatch(deviceLogList) > 0;
        }
        return null;
    }

    /**
     * 获取当天不重复的8位门禁密码
     *
     * @return 当天不重复的8位门禁密码
     * @author blank 2017/10/27 下午4:11
     */
    @Override
    public String fanhuiNewRandomPassword() {

        String randomPassword = doorAccessPwdMapper.queryNewRandomPassword();
        if (randomPassword.length() > 0) {

            if (randomPassword.length() == 1) {
                randomPassword = "0000000" + randomPassword;
            } else if (randomPassword.length() == 2) {
                randomPassword = "000000" + randomPassword;
            } else if (randomPassword.length() == 3) {
                randomPassword = "00000" + randomPassword;
            } else if (randomPassword.length() == 4) {
                randomPassword = "0000" + randomPassword;
            } else if (randomPassword.length() == 5) {
                randomPassword = "000" + randomPassword;
            } else if (randomPassword.length() == 6) {
                randomPassword = "00" + randomPassword;
            } else if (randomPassword.length() == 7) {
                randomPassword = "0" + randomPassword;
            }
            log.debug("当前生成的新8位随机密码是: " + randomPassword);
            return randomPassword;
        }
        return fanhuiNewRandomPassword();
    }

    /**
     * 查询订单对应的门禁 QRCode
     *
     * @param orderId 订单 ID
     * @return 查询2分钟内有效的 QRCode Base64 String
     * @author blank 2017/10/30 下午3:11
     */
    @Override
    public Map<String, Object> updateAndGetNewQRCodeByOrderId(Integer orderId) throws OrderNotFoundException {

        Assert.notNull(orderId, "orderId can not be null!");
        Map<String, Object> resultMap = new HashMap<>();


        OrderCourse orderCourse = orderInfoMapper.queryCourseStartTimeByOrderId(orderId);
        if (orderCourse != null) {

            if (orderCourse.getOrderType() != null && orderCourse.getOrderType().equals(1)
                    || orderCourse.getOrderType() != null && orderCourse.getOrderType().equals(4)) {
                //团课 自助


                String pwdStatusWord = this.getPwdStatusWord(orderCourse.getCourseStartTime(), "000000", orderCourse);
                if (!pwdStatusWord.equals("000000")) {
                    resultMap.put("password", pwdStatusWord);
                } else {
                    resultMap.put("password", "000000");
                    String newRandomPassword = this.fanhuiNewRandomPassword();
                    if (resultMap.get("password").equals("000000")) {
                        try {
                            this.insertOrUpdateNewDoorAccessPwd(orderCourse, null, newRandomPassword, null, null);
                        } catch (Exception e) {
                            e.printStackTrace();
                            log.error("更新新的密码到door_access_pwd 表中出错 " + e.getMessage() + e.getCause(), e);
                        }
                    }
//                    Date now = new Date();//当前 QRCode 有效2分钟可重复获取
                    String qrCodeBase64 = QRCodeUtil.createQRCodeBase64(orderCourse.getUserId().toString(), orderCourse.getMacLast4(), newRandomPassword, null, null);
                    resultMap.put("passwordQRCode", qrCodeBase64);
                }


            } else if (orderCourse.getOrderType() != null && orderCourse.getOrderType().equals(2)) {
                //私教
                //resultMap.put("password", "课前请预先联系私教教练");
                // 教练按照日程得时间来显示
                CourseSign courseSign = courseSignMapper.queryPtCourseCourseSignMaxToDayByOrderId(orderId);
                if (courseSign == null){
                    resultMap.put("password", "与教练确定上课时间后，在开始的前20分钟显示");
                }else{
                    String pwdStatusWord = this.getPwdStatusWord(courseSign.getStartTime(), "000000", orderCourse);
                    if (!pwdStatusWord.equals("000000")) {
                        resultMap.put("password", "与教练确定上课时间后，在开始的前20分钟显示");
                    } else {
                        resultMap.put("password", "000000");
                        String newRandomPassword = this.fanhuiNewRandomPassword();
                        if (resultMap.get("password").equals("000000")) {
                            try {
                                this.insertOrUpdateNewDoorAccessPwd(orderCourse, null, newRandomPassword, null, null);
                            } catch (Exception e) {
                                e.printStackTrace();
                                log.error("更新新的密码到door_access_pwd 表中出错 " + e.getMessage() + e.getCause(), e);
                            }
                        }
//                    Date now = new Date();//当前 QRCode 有效2分钟可重复获取
                        String qrCodeBase64 = QRCodeUtil.createQRCodeBase64(orderCourse.getUserId().toString(), orderCourse.getMacLast4(), newRandomPassword, null, null);
                        resultMap.put("passwordQRCode", qrCodeBase64);
                    }
                }
            } else if (orderCourse.getOrderType() != null && orderCourse.getOrderType().equals(3)) {
                //檬营

                //处理檬檬当前上课序号 教练签到销课逻辑 现在按当前上课时间逻辑处理
//                int courseIndex = 0;
//                if (orderCourse.getWeek() == null && ( orderCourse.getWeekly().equals(0) || orderCourse.getWeekly().equals(1) )) {
//                    //第一节课还没开启签到 或 第一节课已开启签到 都返回第1节课
//                    courseIndex = 1;
//                } else if (orderCourse.getWeek() != null && orderCourse.getWeekly().equals(0)) {
//                    //已经签完了第1节课 后面的第N节课还没开启签到
//                    courseIndex = orderCourse.getWeek() + 1;
//                } else if (orderCourse.getWeek() != null && orderCourse.getWeekly().equals(1)) {
//                    //已经签完了第1节课 后面的第N节课已开启签到
//                    courseIndex = orderCourse.getWeek();
//                }
//                courseIndex -=1;//index 需要-1
//                String[] campClassTime = orderCourse.getCampClassTime().split(",");

//                Date startTime = DateUtil.parseUtilDate(campClassTime[courseIndex], DateUtil.FMT_DATE_YYYYMMDDHHMM);

                //直接按新的 来处理上课时间 不管教练是否已经签到
                if (StringUtils.isNotBlank(orderCourse.getCampClassTime())) {
                    String[] campClassTime = orderCourse.getCampClassTime().split(",");
                    Date startTime = null;
                    Date endTime = null;
                    for (String time : campClassTime) {
                        startTime = DateUtil.parseUtilDate(time, DateUtil.FMT_DATE_YYYYMMDDHHMM);
                        endTime = DateUtil.addMinites(startTime, 90);
                        if (new Date().before(endTime)) {
                            break;
                        }
                    }

                    //先判断檬营是否已经结束
                    if (endTime != null && new Date().after(endTime)) {
                        //当前已经是最后一节课 且当前时间已过最后一节课的开课时间90分钟 就算结束
                        resultMap.put("password", "您的订单已完成");
                    } else {
                        // 还有课

                        String pwdStatusWord = this.getPwdStatusWord(startTime, "000000", orderCourse);
                        if (!pwdStatusWord.equals("000000")) {
                            resultMap.put("password", pwdStatusWord);
                        } else {
                            resultMap.put("password", "000000");
                            String newRandomPassword = this.fanhuiNewRandomPassword();
                            if (resultMap.get("password").equals("000000")) {
                                try {
                                    this.insertOrUpdateNewDoorAccessPwd(orderCourse, null, newRandomPassword, null, null);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                    log.error("更新新的密码到door_access_pwd 表中出错 " + e.getMessage() + e.getCause(), e);
                                }
                            }
                            String qrCodeBase64 = QRCodeUtil.createQRCodeBase64(orderCourse.getUserId().toString(), orderCourse.getMacLast4(), newRandomPassword, null, null);
                            resultMap.put("passwordQRCode", qrCodeBase64);
                        }
                    }
                }
            }else if(orderCourse.getOrderType() != null && orderCourse.getOrderType().intValue() == OrderContants.OrderType.physical_examination.getIndex()
                    || orderCourse.getOrderType() != null && orderCourse.getOrderType().intValue() == OrderContants.OrderType.secret_experience.getIndex()){
                CourseSign courseSign = courseSignMapper.queryPtCourseCourseSignMaxToDayByOrderId(orderId);
                if (courseSign == null){
                    resultMap.put("password", "与教练确定上课时间后，在开始的前20分钟显示");
                }else{
                    String pwdStatusWord = this.getPwdStatusWord(courseSign.getStartTime(), "000000", orderCourse);
                    if (!pwdStatusWord.equals("000000")) {
                        resultMap.put("password", "与教练确定上课时间后，在开始的前20分钟显示");
                    } else {
                        resultMap.put("password", "000000");
                        String newRandomPassword = this.fanhuiNewRandomPassword();
                        if (resultMap.get("password").equals("000000")) {
                            try {
                                this.insertOrUpdateNewDoorAccessPwd(orderCourse, null, newRandomPassword, null, null);
                            } catch (Exception e) {
                                e.printStackTrace();
                                log.error("更新新的密码到door_access_pwd 表中出错 " + e.getMessage() + e.getCause(), e);
                            }
                        }
//                    Date now = new Date();//当前 QRCode 有效2分钟可重复获取
                        String qrCodeBase64 = QRCodeUtil.createQRCodeBase64(orderCourse.getUserId().toString(), orderCourse.getMacLast4(), newRandomPassword, null, null);
                        resultMap.put("passwordQRCode", qrCodeBase64);
                    }
                }
            }
            return resultMap;
        }

        throw new OrderNotFoundException("找不到对应订单");
    }

    /**
     * 根据用户类型返回门禁二维码密码
     *
     * @param storeId       门店 ID
     * @param relationType  1教练 2 系统用户 3 前端微信用户
     * @param userId 用户 ID
     * @return QRCode Base64
     */
    @Override
    public String returnNewQRCodeByUserType(Integer storeId, Integer relationType, Integer userId, Date startTime, Date endTime) {

        DoorAccessPwd accessPwd = new DoorAccessPwd();
        accessPwd.setRelationType(relationType);
        accessPwd.setRelationId(userId);
        //当天不重复的密码
        String password = this.fanhuiNewRandomPassword();

        if (startTime == null) {

            startTime = new Date();
        }
        if (endTime == null) {
            endTime = DateUtil.addMinites(startTime, 2);
        }

        accessPwd.setStoreId(storeId);
        accessPwd.setPassword(password);
        accessPwd.setStartTime(startTime);
        accessPwd.setEndTime(endTime);
        accessPwd.setCreatedTime(startTime);
        accessPwd.setRemark(relationType == 1 ? "创建教练二维码密码" : relationType == 2 ? "创建系统用户二维码密码" : "创建微信用户二维码密码");
        doorAccessPwdMapper.insertSelective(accessPwd);
        AccessDevice accessDevice = new AccessDevice();

        accessDevice.setStoreId(storeId);
        accessDevice = accessDeviceMapper.selectOne(accessDevice);


        if (accessDevice != null && accessDevice.getDeviceSerialId() != null) {
            String macLast4 = accessDevice.getDeviceSerialId().substring(accessDevice.getDeviceSerialId().length() - 4);
            return QRCodeUtil.createQRCodeBase64(userId.toString(), macLast4, password, startTime, endTime);

        } else {
            throw new RuntimeException("根据门店 ID找不到对应门店的门禁设备 \n error could not find accessDevice as same as storeId " + storeId);
        }

    }


    /**
     * 将新生成的密码插入或才更新到当前订单密码表中 防止开门校验密码错误
     *
     * @param orderInfo 订单 ID
     * @param password  新的密码
     * @param startTime 密码有效时间
     * @param endTime   密码失效时间
     * @return true 更新成功 / false 更新失败
     */

    private boolean insertOrUpdateNewDoorAccessPwd(OrderInfo orderInfo, Integer storeId, String password, Date startTime, Date endTime) throws OrderException {

        if (orderInfo == null || orderInfo.getId() == null) throw new OrderException("orderId can not be null!");
        if (StringUtils.isBlank(password)) throw new OrderException("order password can not be null!");

        DoorAccessPwd accessPwd = new DoorAccessPwd();
        accessPwd.setRelationType(0);//0 是订单
        accessPwd.setRelationId(orderInfo.getId());

        DoorAccessPwd doorAccessPwdDb = doorAccessPwdMapper.selectOne(accessPwd);
        Date dateNow = new Date();
        if (doorAccessPwdDb == null) {

            accessPwd.setStoreId(storeId);
            accessPwd.setPassword(password);
            accessPwd.setStartTime(startTime != null ? startTime : dateNow);
            accessPwd.setEndTime(endTime != null ? endTime : DateUtil.addMinites(dateNow, 2));
            accessPwd.setCreatedTime(dateNow);
            accessPwd.setRemark("创建用户二维码密码");
            return doorAccessPwdMapper.insertSelective(accessPwd) > 0;
        } else {

            accessPwd.setStoreId(storeId);
            accessPwd.setId(doorAccessPwdDb.getId());
            accessPwd.setPassword(password);
            accessPwd.setRelationType(0);//0 是订单
            accessPwd.setRelationId(orderInfo.getId());
            accessPwd.setStartTime(startTime != null ? startTime : dateNow);
            accessPwd.setEndTime(endTime != null ? endTime : DateUtil.addMinites(dateNow, 2));
            accessPwd.setUpdatedTime(dateNow);
            accessPwd.setRemark("更新用户二维码密码");
            return doorAccessPwdMapper.updateSelectiveById(accessPwd) > 0;
        }
    }


    /**
     * 返回密码提示文字
     *
     * @param courseDate 订单开始时间
     * @param pwd  门禁密码
     * @return 密码或提示文字
     */
    public String getPwdStatusWord(Date courseDate, String pwd, OrderInfo orderInfo) {
        if ("3".equals(orderInfo.getOrderStatus())) {
            return "你当前正处于排队状态";
        } else if ("2".equals(orderInfo.getOrderStatus())) {
            return "你已成功取消订单";
        } else if ("4".equals(orderInfo.getOrderStatus())) {
            return "您的订单已完成";
        }
        if (courseDate == null) {
            return "订单存在异常请于客服联系";
        }

        Date now = new Date();
        Date now_20 = new Date(courseDate.getTime() - 20 * 60000); // 20分钟前的时间
        String courseTime = DateUtils.format(courseDate, DateUtils.datePatternAllHH);
        String msg;
        if (now.after(now_20)) {
            msg = pwd;

        } else {
            msg = "将于" + (DateUtils.format(courseDate, DateUtils.shortDatePattern)).replaceAll("-", ".") + " "
                    + DateUtils.getWeekDay(courseTime) + " " + DateUtils.format(now_20, DateUtils.shortTimePattern)
                    + "显示";
        }

        return msg;
    }

    /**
     * 查询教练密码
     *
     * @param coachId 教练ID
     * @return
     */
    @Override
    public List<DoorAccessPwd> queryDoorPwdByCoachId(Integer coachId) {
        return doorAccessPwdMapper.queryDoorAccessPwdListByRelation(coachId, 1);
    }

    /**
     * 查询管理系统用户密码
     *
     * @param sysUserId 系统用户ID
     * @return
     */
    @Override
    public List<DoorAccessPwd> querySystemUserPwdBySysUserId(Integer sysUserId) {
        return doorAccessPwdMapper.queryDoorAccessPwdListByRelation(sysUserId, 2);
    }

    /**
     * 查询管理系统用户
     *
     * @param mobile
     * @return
     */
    @Override
    public SysUser querySysUserByMobile(String mobile) {
        return sysUserMapper.querySysUserByMobile(mobile);
    }


}
